package com.hbfec.fileserver.task;

import com.hbfec.fileserver.constant.CacheKeys;
import com.hbfec.fileserver.pojo.File;
import com.hbfec.fileserver.service.CacheService;
import com.hbfec.fileserver.service.DbService;
import com.hbfec.fileserver.service.SimpleToolsService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

/**
 * 文件信息持久化定时任务
 */
@Component
public class FileBatchUpdateTask {
    private static final Logger LOGGER = LoggerFactory.getLogger(FileBatchUpdateTask.class);

    private boolean dequeueBackup;

    @Value("${fileserver.dateformat}")
    private String dateFormat;
    @Value("${fileserver.persist.batch-limit}")
    private Integer batchLimit;

    @Autowired
    private DbService db;
    @Autowired
    private CacheService cache;
    @Autowired
    private SimpleToolsService tools;

    public FileBatchUpdateTask() {
        this.dequeueBackup = true;
    }

    /**
     * 定时任务方法
     */
    @Scheduled(fixedDelayString = "${fileserver.persist.task-fixed-delay}")
    public void run() {
        List<String> records = null;
        try {
            if (dequeueBackup) {
                records = cache.lrangeAll(CacheKeys.FILE_QUEUE_BACKUP);
            } else {
                records = cache.rpoplpush(CacheKeys.FILE_QUEUE, CacheKeys.FILE_QUEUE_BACKUP, batchLimit);
            }
        } catch (Exception ex) {
            LOGGER.error("从缓存获取数据时出现异常", ex);
            return;
        }
        List<File> replacedFiles = new ArrayList<File>();
        for (String record : records) {
            if (record == null) {
                continue;
            }
            String[] recordArray = record.split(" \\| ", 7);
            try {
                replacedFiles.add(
                        new File(recordArray[0], recordArray[1], recordArray[2], Long.valueOf(recordArray[3]),
                                tools.strToDate(recordArray[4], dateFormat), recordArray[5], recordArray[6]));
            } catch (Exception ex) {
                LOGGER.error(String.format("从缓存中读出了格式有问题的数据：%s", record), ex);
            }
        }
        try {
            if (!replacedFiles.isEmpty()) {
                db.updateFile(replacedFiles);
            }
            dequeueBackup = false;
        } catch (Exception ex) {
            LOGGER.error("入库失败，已回滚", ex);
            dequeueBackup = true;
            return;
        }
        // 准备待删除的数据
        List<String> deletedKeyList = new ArrayList<String>();
        deletedKeyList.add(CacheKeys.FILE_QUEUE_BACKUP);
        try {
            records = cache.lrangeAll(CacheKeys.FILE_QUEUE_BACKUP);
        } catch (Exception ex) {
            LOGGER.error("在准备待删除数据时，从缓存备份数据列表中获取数据时出现异常", ex);
            return;
        }
        for (String record : records) {
            if (record == null) {
                continue;
            }
            String[] recordArray = record.split(" \\| ", 7);
            try {
                deletedKeyList.add(String.format("%s%s_%s", CacheKeys.FILE_STATUS, recordArray[0], recordArray[6]));
            } catch (Exception ex) {
                LOGGER.error(String.format("在准备待删除数据时，从缓存中读出了格式有问题的数据，理论上不应该发生该异常：%s", record), ex);
                return;
            }
        }
        // 执行删除。删除失败后，无需将dequeueBackup设置成true。当下次操作成功时，将会连同此次的备份一起删除
        try {
            cache.del(deletedKeyList.toArray(new String[deletedKeyList.size()]));
        } catch (Exception ex) {
            LOGGER.error("从缓存删除数据时出现异常", ex);
        }
    }
}
